﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using OConf.NetCore.Common;
using OConf.NetCore.Model;
using OConf.NetCore.Options;
using OConf.NetCore.Static;

namespace OConf.NetCore.Extensions
{
    public static class ConfigExtensions
    {
        /// <summary>
        /// 准备初始化配置信息
        /// </summary>
        /// <param name="hostBuilder"></param>
        /// <param name="act"></param>
        /// <returns></returns>
        public static IHostBuilder PrepareInitConfig(this IHostBuilder hostBuilder, Action<ConfigNameSpaceOptions> act)
        {
            ConfigNameSpaceOptions opt = new ConfigNameSpaceOptions();
            act.Invoke(opt);

            return hostBuilder;
        }

        /// <summary>
        /// 准备初始化配置信息
        /// </summary>
        /// <param name="hostBuilder"></param>
        /// <param name="act"></param>
        /// <returns></returns>
        public static IHostBuilder PrepareInitConfig(this IHostBuilder hostBuilder, Action<ConfigNameSpaceOptions, ConfigLoadingOptions> act)
        {
            ConfigNameSpaceOptions opt = new ConfigNameSpaceOptions();
            ConfigLoadingOptions loadingOptions = new ConfigLoadingOptions();
            act.Invoke(opt, loadingOptions);

            return hostBuilder;
        }

        /// <summary>
        /// 加载配置文件
        /// </summary>
        /// <param name="hostBuilder"></param>
        /// <returns></returns>
        public static IHostBuilder LoadingConfig(this IHostBuilder hostBuilder)
        {
            hostBuilder = hostBuilder.ConfigureAppConfiguration(config =>
            {
                InitConfiguration(config.Build());

                DownloadConfig.LoadingConfigFile(config);
            });

            hostBuilder = hostBuilder.ConfigureServices(services =>
            {
                services.AddHttpRequest();
                services.AddConfig();
            });

            return hostBuilder;
        }

        /// <summary>
        /// 注入Http请求服务
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection AddHttpRequest(this IServiceCollection services)
        {
            services.AddHttpClient();
            HttpRequestUnit.InitHttpUnit(services.BuildServiceProvider().GetService<IHttpClientFactory>());
            return services;
        }

        /// <summary>
        /// 添加配置服务
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection AddConfig(this IServiceCollection services)
        {
            //注入后台服务
            services.AddHostedService<ConfigJob>();
            return services;
        }

        /// <summary>
        /// 向服务端获取配置信息
        /// </summary>
        /// <param name="configuration"></param>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="Exception"></exception>
        private static void InitConfiguration(IConfiguration configuration)
        {
            string _server = configuration["OConf:Server"];
            string _programName = configuration["OConf:ProgramName"];
            string _secretKey = configuration["OConf:SecretKey"];

            if (string.IsNullOrEmpty(_server) || string.IsNullOrEmpty(_programName))
            {
                throw new ArgumentException("ServerIP or ProgramName IsNullOrEmpty");
            }

            FileCore.CreateDirectory(Cache.saveDicPath);
            string url = _server.TrimEnd('/') + "/api/ConfigBackEnd/V2/GetBackProgramConfigInfo";
            List<string> nameSpaces = ConfigNameSpaceOptions.GetNameSpace();

            #region 从服务端获取配置信息
            SortedDictionary<string, object> requestParam = new SortedDictionary<string, object>();
            requestParam.Add("ProgramName", _programName);
            requestParam.Add("NameSpaces", nameSpaces);
            requestParam.Add("Key", _secretKey);
            string sign = JsonConvert.SerializeObject(requestParam).MD5Encrypt32();
            requestParam.Add("Sign", sign);

            string resJson = HttpRequestUnit.PostAsync(url, requestParam, timeout: 10).Result;
            ReturnData<BackProgramConfigInfo> result = JsonConvert.DeserializeObject<ReturnData<BackProgramConfigInfo>>(resJson);
            if (result.Code != (int)StatusCode.服务器成功返回请求数据)
            {
                throw new Exception("获取远端配置信息失败," + result.Msg);
            }

            //保存配置信息
            ConfigCommon.SaveConfigInfo(result.Data);
            #endregion
        }
    }
}
